package com.fable.sp.core.template.freemarker;

import com.fable.sp.core.util.HttpUtil;
import com.fable.sp.core.util.UrlUtils;
import freemarker.template.*;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.List;

/**
 * url函数,支持以下语法:
 * ${url} 当前url
 * ${url("/user")} 自定义url
 * ${url("p1","v1", "p2","v2")} 当前url附加2对参数,必须为偶数个参数,参数写法
 * ${url({"name":"mouse", "price":50})} 当前url附加2对参数,map写法
 * ${url('/user',"p1","v1", "p2","v2")} 自定义url,附加参数
 * ${url('user',"p1","v1","p2",["v21","v22"])} 自定义url,附加参数
 * ${url('/item',{"name":"mouse", "price":50})} 自定义url,附加map参数
 * <p/>
 */
public class UrlMethod implements TemplateMethodModelEx, TemplateScalarModel {
    @Override
    public Object exec(List args) throws TemplateModelException {
        int len = args.size();

        HttpServletRequest request = HttpUtil.getCurrentRequest();
        if (len == 0) {
            return request.getRequestURL();
        }
        String currentPath = request.getRequestURI();
        HashMap<String, Object> params = new HashMap<String, Object>();
        Object arg0 = args.get(0);
        if (arg0 instanceof TemplateScalarModel) {
            String customPath = request.getContextPath() + ((TemplateScalarModel) arg0).getAsString();
            if (len == 1) {//customPath
                return customPath;
            } else if (len % 2 == 1) {//customPath + listAr
                return UrlUtils.build(customPath, mergeList(params, args, 1, len));
            } else {
                Object arg1 = args.get(1);
                if (arg1 instanceof TemplateHashModelEx) {//customPath + mapArg
                    return UrlUtils.build(currentPath, mergeMap(params, (TemplateHashModelEx) arg1));
                } else {//currentPath + listArg
                    params.putAll(request.getParameterMap());
                    return UrlUtils.build(currentPath, mergeList(params, args, 0, len));
                }
            }
        } else if (arg0 instanceof TemplateHashModelEx) {
            params.putAll(request.getParameterMap());
            return UrlUtils.build(currentPath, mergeMap(params, (TemplateHashModelEx) arg0));
        } else {
            throw new TemplateModelException("Unsupport arg types");
        }
    }

    private HashMap<String, Object> mergeList(HashMap<String, Object> map, List args, int start, int len) throws TemplateModelException {
        for (int i = start; i < len; i++) {
            map.put(args.get(i).toString(), FmUtils.unwrap(args.get(++i)));
        }
        return map;
    }

    private HashMap<String, Object> mergeMap(HashMap<String, Object> map, TemplateHashModelEx hm) throws TemplateModelException {
        TemplateModelIterator it = hm.keys().iterator();
        while (it.hasNext()) {
            String key = it.next().toString();
            map.put(key, FmUtils.unwrap(hm.get(key)));
        }
        return map;
    }

    @Override
    public String getAsString() throws TemplateModelException {
        HttpServletRequest request = HttpUtil.getCurrentRequest();
        return request != null ? request.getRequestURL().toString() : Env.baseUrl();
    }
}
